package com.ruge.core;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruge.core.config.FastJson2JsonRedisSerializer;
import com.ruge.core.config.JpaAuditorAware;
import com.ruge.core.config.SwaggerConfig;
import com.ruge.core.exception.GlobalExceptionHandler;
import com.ruge.core.exception.SpringBootErrorController;
import com.ruge.core.log.ReqRespLoggingFilter;
import com.ruge.core.log.ReqRespLoggingProperties;
import com.ruge.core.log.SwaggerLogAspect;
import com.ruge.core.properties.SwaggerProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * description: WebCommonConfig
 * create time at 2022/6/6 11:25
 *
 * @author alice.ruge
 * @since 0.0.3
 */
@Configuration
@EnableJpaAuditing
@EnableConfigurationProperties({ReqRespLoggingProperties.class})
public class WebCommonConfig {

    private final ReqRespLoggingProperties reqRespLoggingProperties;

    public WebCommonConfig(ReqRespLoggingProperties reqRespLoggingProperties) {
        this.reqRespLoggingProperties = reqRespLoggingProperties;
    }

    /**
     * yml注入swagger属性配置
     *
     * @return {@link SwaggerProperties}
     */
    @Bean
    public SwaggerProperties swaggerProperties() {
        return new SwaggerProperties();
    }

    /**
     * 读取swagger动态配置
     *
     * @return {@link SwaggerConfig}
     */
    @Bean
    public SwaggerConfig swaggerConfig() {
        return new SwaggerConfig();
    }

    /**
     * 全局异常处理
     *
     * @return {@link GlobalExceptionHandler}
     */
    @Bean
    public GlobalExceptionHandler globalExceptionHandler() {
        return new GlobalExceptionHandler();
    }

    /**
     * springboot 默认状态码封装
     *
     * @return {@link SpringBootErrorController}
     */
    @Bean
    public SpringBootErrorController springBootErrorController() {
        return new SpringBootErrorController();
    }

    @Bean
    @ConditionalOnMissingBean(name = {"loggingFilter"})
    public ReqRespLoggingFilter loggingFilter() {
        return new ReqRespLoggingFilter(this.reqRespLoggingProperties);
    }

    /**
     * jpa 注入用户信息
     *
     * @return {@link JpaAuditorAware}
     */
    @Bean
    public JpaAuditorAware jpaAuditorAware() {
        return new JpaAuditorAware();
    }

    /**
     * swagger aop监听参数
     *
     * @return {@link SwaggerLogAspect}
     */
    @Bean
    public SwaggerLogAspect swaggerLogAspect() {
        return new SwaggerLogAspect();
    }

    /**
     * redisTemplate
     *
     * @param connectionFactory redis连接工厂
     * @return {@link RedisTemplate}
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(@Autowired RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        template.setKeySerializer(keySerializer());
        template.setValueSerializer(valueSerializer());

        template.setHashKeySerializer(keySerializer());
        template.setHashValueSerializer(valueSerializer());
        template.afterPropertiesSet();
        return template;
    }

    /**
     * 创建redis的key序列化规则
     *
     * @return 序列化
     */
    private RedisSerializer<?> keySerializer() {
        return new StringRedisSerializer();
    }

    /**
     * 值使用jackson进行序列化
     *
     * @return 序列化
     */
    private RedisSerializer<?> valueSerializer() {
        FastJson2JsonRedisSerializer<Object> serializer = new FastJson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        serializer.setObjectMapper(mapper);
        return serializer;
    }


}
